import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_graphics_view/flutter_graphics_view.dart';

void main() {
  runApp(SimpleTestWidget());
}

class SimpleTestWidget extends StatefulWidget {
  @override
  _SimpleTestWidgetState createState() {
    return _SimpleTestWidgetState();
  }
}

class _SimpleTestWidgetState extends State<SimpleTestWidget> {
  MyPolicy myPolicy = MyPolicy();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: Stack(
            children: [
              Container(
                color: Colors.blue,
              ),
              Padding(
                padding: EdgeInsets.all(20),
                child: FlutterGraphicsViewWidget(
                  graphicsViewContext: GraphicsViewContext(
                    policySet: myPolicy,
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class MyPolicy extends PolicySet
    with
        MyInitPolicy,
        MyGraphicsItemDisplayPolicy,
        MyScenePolicy,
        MySceneWidgetsPolicy,
        MyGraphicsItemPolicy,
        SceneControlPolicy {}

mixin MyInitPolicy implements InitPolicy {
  @override
  initializeGraphicsView() {
    sceneWriter.state.setSceneColor(Colors.grey);
  }
}

mixin MyGraphicsItemDisplayPolicy implements GraphicsItemDisplayPolicy {
  @override
  Widget showGraphicsItemBody(ItemModelData modelData) {
    return Container(
      decoration: BoxDecoration(
          color: (modelData.userData as MyItemData).color,
          border: Border.all(
            width: 2,
            color: (modelData.userData as MyItemData).isHighlightVisible
                ? Colors.pink
                : Colors.black,
          )),
      child: Center(
        child: Text('item'),
      ),
    );
  }
}

class MyItemData {
  bool isHighlightVisible = false;
  Color color =
      Color((math.Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0);

  showHighlight() {
    isHighlightVisible = true;
  }

  hideHighlight() {
    isHighlightVisible = false;
  }
}

mixin MyScenePolicy implements ScenePolicy {
  @override
  onSceneTapUp(TapUpDetails details) {
    sceneWriter.model.addItem(ItemModelData(
      size: Size(80, 60),
      position: sceneReader.state.fromSceneCoordinates(details.localPosition),
      userData: MyItemData(),
    ));
  }
}

mixin MySceneWidgetsPolicy implements SceneWidgetsPolicy {
  @override
  List<Widget> showCustomWidgetsOnSceneBackground(BuildContext context) {
    return [
      CustomPaint(
          size: Size.infinite,
          painter: BackgroundPainter(
              offset: sceneReader.state.position / sceneReader.state.scale,
              scale: sceneReader.state.scale,
              matchParentSize: false,
              gridLineColor: Colors.blue)),
    ];
  }
}

mixin MyGraphicsItemPolicy implements GraphicsItemPolicy {
  late Offset lastFocalPoint;

  @override
  onGraphicsItemScaleStart(String itemId, ScaleStartDetails details) {
    lastFocalPoint = details.localFocalPoint;
  }

  @override
  onGraphicsItemScaleUpdate(String itemId, ScaleUpdateDetails details) {
    Offset posDelta = details.localFocalPoint - lastFocalPoint;
    sceneWriter.model.moveItem(itemId, posDelta);
    lastFocalPoint = details.localFocalPoint;
  }
}
